import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { User, UserDocument } from './entities/user.entity';
import { Model } from 'mongoose';
import { snowflake } from 'src/util/Snowflake';
import { ConfigService } from '@nestjs/config';
import * as bcrypt from 'bcrypt';
import { BaseService } from 'src/common/mongodb/BaseService';
import { CreateUserInput, LoginUserInput, UpdatePasswordInput } from './dto/inputDto';

@Injectable()
export class UserService extends BaseService<UserDocument> {
  constructor(
    @InjectModel(User.name)
    private userModel: Model<UserDocument>,
    private configService: ConfigService,
  ) {
    super(userModel, ['role']);
  }

  async createUserInfo(createUserInput: CreateUserInput) {
    createUserInput.isDel = false;
    createUserInput.createTime = Date.now();
    const hash = await bcrypt.hash(
      createUserInput.password,
      Number(this.configService.get<string>('SALT_ROUND')),
    );
    const createUser = new this.userModel({
      ...createUserInput,
      password: hash,
    });
    createUser._id = snowflake.nextId();
    return createUser.save();
  }

  async updateUserPwd(id: number, updateUserInput: UpdatePasswordInput) {
    const hash = await bcrypt.hash(
      updateUserInput.password,
      Number(this.configService.get<string>('SALT_ROUND')),
    );
    const updateUser = new this.userModel({
      ...updateUserInput,
      password: hash,
    });

    return this.userModel.findByIdAndUpdate(id, updateUser, {
      new: true,
    });
  }

  async loginUser(loginInput: LoginUserInput) {
    const { email, password } = loginInput;
    const user = await this.userModel.findOne(
      { $or: [{ email: email }, { name: email }] }
    );
    if (!user) {
      throw new Error('Invalid credentials');
    }

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch) {
      throw new Error('Password or email address incorrect');
    }
    return user;
  }
}
